﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.SessionState;
using System.Web.Routing;
using System.Reflection;
using SimpleRest.Core.Routing;
using SimpleRest.Core.Routing.Handlers;

namespace SimpleRest.Core.Routing
{
    /// <summary>
    /// Route that is associated to an actual service operation.
    /// </summary>
    public class OperationRoute// : Route
    {
        /// <summary>
        /// The target service associated to this service operation.
        /// </summary>
        public readonly Type ServiceType;
        /// <summary>
        /// The configuration object associated to the service operation in which this reoute is being registered.
        /// </summary>
        public readonly Configuration Configuration;
        /// <summary>
        /// The target service method that this operation is targeting within the service type.
        /// </summary>
        public readonly MethodInfo TargetMethod;
        /// <summary>
        /// The actual route Uri for this associated service operation.
        /// </summary>
        public readonly string RouteUri;
        /// <summary>
        /// The http method in which this operation is associated.
        /// </summary>
        public readonly string HttpMethod;
        /// <summary>
        /// RouteUri with any query string parameter's.
        /// </summary>
        public readonly string RouteUriWithQuerystring;

        public OperationRoute(Type service, MethodInfo targetMethod, Configuration configuration)
        {
            if (targetMethod == null)
                throw new Exception("Unable to register service operation for null service type.");

            this.ServiceType = service;

            this.RouteUriWithQuerystring = RouteUtility.GetRouteUri(targetMethod);
            this.RouteUri = RouteUtility.GetRoutePrefix(this.ServiceType, this.RouteUriWithQuerystring);

            this.Configuration = configuration;
            this.HttpMethod = RouteUtility.GetHttpMethod(targetMethod);
            this.TargetMethod = targetMethod;
        }

        internal Route _route;
        internal Route Route
        {
            get 
            {
                if (_route == null)
                {
                    string routePrefix = RouteUtility.GetRoutePrefix(this.ServiceType, this.TargetMethod);
                    _route = new Route(routePrefix, new RouteHandler(routePrefix));
                    HttpMethodConstraint methodConstraints = new HttpMethodConstraint(new string[] { this.HttpMethod });
                    _route.Constraints = new RouteValueDictionary { { "httpMethod", methodConstraints }};
                }

                return _route;
            }
        }
    }
}
